<template>
  <div
    v-if="!initializing && pageInfo.type === '普通'"
    :class="['cc-page cc-flex-column cc-grow-height', pageInfo.cssName || '']"
    :style="fullHeight ? 'height: 100%;' : '1px'"
  >
    <page-comp
      v-for="(comp, index) in pageInfo.compList.filter(item => item.showComp === '1')"
      :key="index"
      :ref="el => setRefs(el, comp)"
      :pageCompId="comp.id"
      :operate="operate"
      :inputParam="inputParam"
      :initData="initData"
      :disabled="disabled"
      :class="pageInfo.compList.filter(item => item.showComp === '1').length > 1 ? 'cc-page-comp-auto-height' : ''"
    >
      <slot />
    </page-comp>
  </div>
  <div
    v-else-if="!initializing && pageInfo.type === '标签'"
    :class="['cc-page', pageInfo.cssName || '']"
  >
    <el-tabs
      ref="tabsRef"
      v-model="activeTabName"
      :tab-position="tabPosition"
      class="cc-page-tabs"
      :style="'min-height: ' + autoHeight + 'px'"
      @tab-click="handleTabClick"
    >
      <el-tab-pane
        v-for="(comp, index) in pageInfo.compList.filter(item => item.showComp === '1')"
        :key="index"
        class="cc-page-tab-item cc-grow-height"
        :name="comp.id"
      >
        <template #label>
          <el-badge
            :value="badgeValue[comp.name] || 0"
            :show-zero="false"
          >{{comp.name}}</el-badge>
        </template>
        <page-comp
          :ref="el => setRefs(el, comp)"
          :pageCompId="comp.id"
          :operate="operate"
          :disabled="disabled"
          :inputParam="inputParam"
        />
      </el-tab-pane>
    </el-tabs>
  </div>
  <visual-page
    v-else-if="!initializing && pageInfo.type === '可视化'"
    ref="visualPageRef"
    :dataPageId="dataPageId"
    :pageInfo="pageInfo"
    :operate="operate"
    :inputParam="inputParam"
  />
</template>

<script setup>
import { ref, onMounted, nextTick, provide, inject } from 'vue';
import PageComp from '@/codeless/view/page-comp.vue';
import VisualPage from '@/visual/view/page.vue';
import api from "@/http/api";
import { ElMessage } from "element-plus";
import { getPage } from '@/utils/codeless';

const emit = defineEmits(['updatePageName', 'showDialogButton']);
const props = defineProps({
  dataPageId: String,
  pageInfo: Object,
  operate: {
    type: String,
    default: '',
  },
  copyData: {
    type: Boolean,
    default: false
  },
  initData: {
    type: Object,
    default: () => {}
  },
  inputParam: {
    type: Object,
    default: () => {}
  },
  disabled: {
    type: Boolean,
    default: false
  },
  fullHeight: {
    type: Boolean,
    default: false
  },
  dialogMode: {
    type: Boolean,
    default: false
  }
});

const initializing = ref(true);
const tabsRef = ref();
const autoHeight = ref(null);
const pageCompRefs = ref({});
const visualPageRef = ref({});
const pageInfo = ref({});
const tabPosition = ref('top');
const activeTabName = ref('');
const badgeValue = ref({});
provide('dialogMode', props.dialogMode || false);
provide('showDialogButton', (buttonList) => {
  emit('showDialogButton', buttonList)
});
provide('page', {
  getPageData: function() {
    return getPageData();
  },

  getPageParam: function() {
    return props.inputParam || {};
  }
});
const permitMenuId = inject('permitMenuId', '');

const setRefs = (el, comp) => {
  if (el) {
    pageCompRefs.value[comp.id] = el;
  }
};

const position = ref({'顶部': 'top', '底部': 'bottom', '左侧': 'left', '右侧': 'right'});
const getTabPosition = (key) => {
  return position.value[key] || 'top';
};

const loadPageInfo = async() => {
  if (props.pageInfo) {
    pageInfo.value = props.pageInfo;
  } else {
    pageInfo.value = await getPage(props.dataPageId, permitMenuId.value);
  }

  if (pageInfo.value.type === '标签') {
    activeTabName.value = pageInfo.value.compList.filter(item => item.showComp === '1')[0].id;
    tabPosition.value = getTabPosition(pageInfo.value.tabPosition || '');
  }
  emit('updatePageName', pageInfo.value.name || '');
};

const loadBadgeValue = async() => {
  if (pageInfo.value.type !== '标签' || !pageInfo.value.tabScriptId) return;

  let res = await api.runScript(pageInfo.value.tabScriptId);
  badgeValue.value = res.data || {};
};

const handleTabClick = (tab) => {
  if (pageInfo.value.tabRefresh === '1') {
    pageCompRefs.value[tab.paneName] && pageCompRefs.value[tab.paneName].refreshCompData();
  }

  const currHeight = tabsRef.value.$el.offsetHeight;
  if (autoHeight.value == null || autoHeight.value < currHeight) {
    autoHeight.value = currHeight;
  }
};

const init = async() => {
  if (!props.dataPageId && !props.pageInfo) {
    return;
  }

  initializing.value = true;
  await loadPageInfo();
  await loadBadgeValue();
  await nextTick(() => initializing.value = false);
};

const validate = (callback) => {
  const promise = new Promise((resolve, reject) => {
    if (pageInfo.value.type === '可视化') {
      visualPageRef.value.validate(valid => {
        if (!valid) {
          reject();
        } else {
          resolve(true);
        }
      }).catch(e => reject(e));
    } else {
      let keys = Object.keys(pageCompRefs.value);
      if (keys.length === 0) {
        resolve(true);
        return;
      }

      const validates = keys.map(key => {
        const component = pageCompRefs.value[key];
        if (!component.validate) {
          return Promise.resolve(true);
        }

        return new Promise((innerResolve, innerReject) => {
          component.validate(valid => {
            if (!valid) {
              innerReject();
            } else {
              innerResolve();
            }
          }).catch(innerReject);
        });
      });

      Promise.all(validates)
        .then(() => {
          resolve(true);
        })
        .catch(reject);
    }
  });

  promise.then(valid => callback(valid));
  return promise;
};

const getData = () => {
  let data = {
    copyData: props.copyData,
    inputParam: props.inputParam
  };
  if (pageInfo.value.type === '可视化') {
    data = Object.assign({}, data, visualPageRef.value.getData());
  } else {
    for (let pageCompId in pageCompRefs.value) {
      let find = pageInfo.value.compList.find(comp => comp.id === pageCompId);
      if (find) {
        if (find.name === 'copyData') {
          ElMessage.error("页面组件名称不能为【copyData】！");
          return;
        } else if (find.name === 'inputParam') {
          ElMessage.error("页面组件名称不能为【inputParam】！");
          return;
        }
        data[find.name] = pageCompRefs.value[pageCompId].getData();
      }
    }
  }

  return data;
};

const getPageData = () => {
  let data = {};
  if (pageInfo.value.type === '可视化') {
    Object.assign(data, visualPageRef.value.getData());
  } else {
    for (let pageCompId in pageCompRefs.value) {
      let find = pageInfo.value.compList.find(comp => comp.id === pageCompId);
      if (find) {
        data[find.name] = pageCompRefs.value[pageCompId].getData();
      }
    }
  }

  return data;
};

onMounted(() => {
  init();
});

defineExpose({ validate, getData });
</script>

<style scoped>
.cc-page {
  overflow: auto;
}
</style>